const fs = require('fs');
const path = require('path');
var cheerio = require('cheerio');

function str_error(error) {
    var msg = null;
    if (error) {
        if (error.message && error.stack) {
            msg = "messge: " + error.message + "\nstack: " + error.stack;
        } else if (error.message)
            console.log("messge:" + error.message);
    } else
        msg = "";
    return msg;
}

var StandardRun02 = function () {
    return new Promise(function (rootResolve) {
        new Promise(function (resolve, reject) {
            var oCtx = {
                oConfig: {}
            };
            resolve(oCtx);
        }).then(function (oCtx) {
            return new Promise(function (resolve, reject) {
                // read config.json
                var sConfig = null;
                try {
                    sConfig = fs.readFileSync(path.resolve("config.json"));

                    // parse JSON
                    if (sConfig) {
                        var oConfig = JSON.parse(sConfig, 'utf8');
                        for (const key in oConfig) {
                            if (oConfig.hasOwnProperty.call(oConfig, key)) {
                                oCtx.oConfig[key] = oConfig[key];
                            }
                        }
                        resolve(oCtx);
                    }
                } catch (error) {
                    console.log("read config.json error. " + error.message + error.stack);
                    reject(error);
                }
            });
        }).then(function (oCtx) {
            return new Promise(function (resolve, reject) {
                // Do read HTML file
                var sHtmlFilePath = oCtx.oConfig.htmlFilePath;
                console.log(sHtmlFilePath);
                var sHtml = fs.readFileSync(path.resolve(sHtmlFilePath));
                var $ = cheerio.load(sHtml);
                var sTopElementId = oCtx.oConfig.topElementId;
                // Do parse account information
                var oTopNode = $("#" + sTopElementId);
                var aCategorys = [];
                var oCategory = null;
                oTopNode.children().each(function (i, elem) {
                    if (i % 2 === 0) {
                        // div / h3
                        oCategory = {
                            "name": $(elem).text().trim(),
                            "account": {
                                columns: [],
                                items: []
                            }
                        };
                        aCategorys.push(oCategory);
                    } else {
                        // div / table / tbody / tr / th
                        $(elem).children().first().children().first().children().each(function (i, th) {
                            oCategory.account.columns.push($(th).text().trim());
                        });
                        // div / table / tbody / tr / td
                        var oIt = $(elem).children().first().children().first().next();
                        const oLast = $(elem).children().first().children().last();
                        while (oIt.toString() !== oLast.toString()) {
                            var aCells = [];
                            oIt.children().each(function (i, td) {
                                aCells.push($(td).text().trim());
                            });
                            oCategory.account.items.push(aCells);
                            oIt = oIt.next();
                        }
                    }
                });
                oCtx.aCategorys = aCategorys;
                resolve(oCtx);
            });
        }).then(function (oCtx) {
            return new Promise(function (resolve, reject) {
                // persist
                var sContent = JSON.stringify(oCtx.aCategorys);
                console.log(sContent);
                fs.writeFileSync(path.resolve("data-1.json"), sContent);
                resolve(oCtx);
            });
        }).then(function (oCtx) {
            return new Promise(function (resolve, reject) {
                for (let i = 0; i < oCtx.aCategorys.length; i++) {
                    const oCate = oCtx.aCategorys[i];
                    var aNewItems = [];
                    for (let j = 0; j < oCate.account.items.length; j++) {
                        var aNewCells = [];
                        const aCells = oCate.account.items[j];
                        for (let k = 4; k < 8; k++) {
                            aNewCells.push(oCate.account.items[j][k]);
                        }
                        aNewItems.push(aNewCells);
                    }
                    oCate.account.items = oCate.account.items.concat(aNewItems);
                }
                var sContent = JSON.stringify(oCtx.aCategorys);
                console.log(sContent);
                fs.writeFileSync(path.resolve("data-2.json"), sContent);
                resolve(oCtx);
            });
        }).then(function (oCtx) {
            return new Promise(function (resolve, reject) {
                const oMap = oCtx.oConfig.label2keyMap;
                var oAccountMasterData = {
                    "ClassSet": [],
                    "AccountSet": []
                };
                for (let i = 0; i < oCtx.aCategorys.length; i++) {
                    const oCategory = oCtx.aCategorys[i];
                    var oClass = {
                        "classNo": i.toString(),
                        "name": oCategory.name
                    };
                    oAccountMasterData.ClassSet.push(oClass);
                    for (let j = 0; j < oCategory.account.items.length; j++) {
                        var oAccount = {
                            "classNo": i.toString()
                        };
                        for (let k = 0; k < 4; k++) {
                            oAccount[oMap[k]] = oCategory.account.items[j][k];
                        }
                        oAccountMasterData.AccountSet.push(oAccount);
                    }
                }
                // persist
                var sContent = JSON.stringify(oAccountMasterData);
                console.log(sContent);
                fs.writeFileSync(path.resolve("data-3.json"), sContent);

                rootResolve();
            });
        }).catch(function (error) {
            console.log("config execution error. " + str_error(error));
        })
    });
}
StandardRun02();